﻿namespace ServiceCore.Utility.Extension
{
    public static class NumberExtractor
    {
        /// <summary>
        /// 数字后面加关键字（ 最高性能版本 - 使用 Span 和手动循环）
        /// </summary>
        /// <param name="input"></param>
        /// <param name="keyWord"></param>
        /// <returns></returns>
        public static int? ExtractNumberAfterGong(ReadOnlySpan<char> input, char keyWord = '共')
        {
            int gongIndex = FindGongIndex(input, keyWord);
            if (gongIndex == -1) return null;

            int numberStart = gongIndex + 1;
            if (numberStart >= input.Length) return null;

            return ParseNumber(input.Slice(numberStart));
        }

        private static int FindGongIndex(ReadOnlySpan<char> input, char keyWord = '共')
        {
            for (int i = 0; i < input.Length - 1; i++)
            {
                if (input[i] == keyWord && char.IsDigit(input[i + 1]))
                {
                    return i;
                }
            }
            return -1;
        }

        private static int? ParseNumber(ReadOnlySpan<char> span)
        {
            int number = 0;
            bool foundDigit = false;

            foreach (char c in span)
            {
                if (char.IsDigit(c))
                {
                    foundDigit = true;
                    number = number * 10 + (c - '0');
                }
                else if (foundDigit)
                {
                    // 遇到非数字字符，停止解析
                    break;
                }
            }

            return foundDigit ? number : null;
        }

        /// <summary>
        /// 数字后面加关键字（ 最高性能版本 - 使用 Span 和手动循环）
        /// </summary>
        /// <param name="input"></param>
        /// <param name="keyWord"></param>
        /// <returns></returns>
        public static decimal? ExtractDecimalAfterGong(ReadOnlySpan<char> input, char keyWord = '共')
        {
            int gongIndex = FindGongIndex(input, keyWord);
            if (gongIndex == -1) return null;

            int numberStart = gongIndex + 1;
            if (numberStart >= input.Length) return null;

            return ParseDecimal(input.Slice(numberStart));
        }
        private static decimal? ParseDecimal(ReadOnlySpan<char> span)
        {
            decimal result = 0;
            bool foundDigit = false;
            bool hasDecimalPoint = false;
            decimal decimalPlace = 0.1m;
            bool isNegative = false;
            int i = 0;

            // 跳过前导空格
            while (i < span.Length && char.IsWhiteSpace(span[i]))
            {
                i++;
            }

            // 检查符号
            if (i < span.Length && (span[i] == '+' || span[i] == '-'))
            {
                isNegative = span[i] == '-';
                i++;
            }

            // 解析数字部分
            while (i < span.Length)
            {
                char c = span[i];

                if (char.IsDigit(c))
                {
                    foundDigit = true;
                    if (hasDecimalPoint)
                    {
                        result += (c - '0') * decimalPlace;
                        decimalPlace *= 0.1m;
                    }
                    else
                    {
                        result = result * 10 + (c - '0');
                    }
                }
                else if (c == '.' && !hasDecimalPoint)
                {
                    hasDecimalPoint = true;
                }
                else if (foundDigit)
                {
                    // 遇到非数字字符（除了第一个小数点），停止解析
                    break;
                }
                else
                {
                    // 在找到任何数字之前遇到无效字符，返回 null
                    return null;
                }

                i++;
            }

            if (isNegative)
            {
                result = -result;
            }

            return foundDigit ? result : null;
        }

        public static long ToLong(this string input)
        { 
            long result = 0;
            long.TryParse(input, out result);
            return result;
        }
    }
}
